﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Management;
using System.Collections;
// namespaces necesarios para conexión a bd
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Data.SqlTypes;



using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace Persistencia_y_capa_de_negocio
{
    /// <summary>
    /// CADUsuario. Componente de acceso a la base de datos usuarios.
    /// </summary>
    public class CADUsuario
    {
        /// <summary>
        /// Representa una instancia de la clase.De forma que no he de crear
        /// una nueva cada vez.
        /// </summary>
        private static readonly CADUsuario instancia = new CADUsuario();
        /// <summary>
        /// Me permite obtener la variable privada instancia de la clase
        /// De esta forma siempre uso el mismo objeto que representa la clase.
        /// </summary>
        public static CADUsuario Instancia
        {
            get { return instancia; }
        }

        /// <summary>
        /// Variable para almacenar la cadena de conexión
        /// </summary>
        private string cadCon;
        private SqlDataAdapter da;
        private SqlConnection c;
        private DataSet vdb;

        /// <summary>
        /// Constructor por defecto de la clase CADUsuario
        /// </summary>
        public CADUsuario()
        {
            try
            {
                cadCon = ConfigurationManager.ConnectionStrings["conexion"].ConnectionString;

                vdb = new DataSet();
                c = new SqlConnection(cadCon);
                da = new SqlDataAdapter("select * from usuarios order by cuenta asc", c);

                da.Fill(vdb, "Usuarios");//Copiamos el contenido de los usuarios al datset local vdb.
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            
            
        }

        /// <summary>
        /// Obtiene una lista con todos los usuarios de la tabla usuarios.
        /// </summary>
        /// <returns> Lista de objetos ENUsuario que contienen los usuarios</returns>
        public ArrayList obtenerUsuarios()
        {
            ArrayList lista = new ArrayList();
            DataTable t = new DataTable();
            t = vdb.Tables["Usuarios"];

            foreach (DataRow r in t.Rows)
            {
                ENUsuario us1 = new ENUsuario();

                // Insertamos los datos en el nuevo usuario.
                us1.IDUsuario= Convert.ToInt32(r["id"]);
                us1.NombreUsuario = r["cuenta"].ToString().Trim();
                us1.PassUsuario = r["password"].ToString().Trim();
                us1.EmailUsuario = r["email"].ToString().Trim();
                us1.FechaRegUsuario = Convert.ToDateTime(r["fechareg"]);
                us1.CXBaseUsuario = Convert.ToInt32(r["coordenada_x"]);
                us1.CYBaseUsuario = Convert.ToInt32(r["coordenada_y"]);
                us1.CXCuadranteUsuario = Convert.ToInt32(r["cuadrante_x"]);
                us1.CYCuadranteUsuario = Convert.ToInt32(r["cuadrante_y"]);
                us1.NombrePlaneta = r["nomplaneta"].ToString().Trim();

                lista.Add(us1);
            }
            return lista;
        }

        /// <summary>
        /// Obtiene un usuario a partir del identificador ID de un usuario
        /// </summary>
        /// <param name="unaID">id del usuario</param>
        /// <returns>Devuelve un objeto de tipo ENUsuario con los datos del usuario indicado</returns>
        public ENUsuario ObtenerUnUsuario(int unaID)
        {
            ENUsuario us1 = new ENUsuario();

            DataTable tabla = new DataTable();
            DataRow r = null;

            tabla = vdb.Tables["Usuarios"];
            string selectUs = "id = \'" + unaID + "\'";
            try
            {
                r = tabla.Select(selectUs)[0];
            }
            catch (Exception)
            {
                return null;
            }
            // Insertamos los datos en el nuevo usuario.
            us1.IDUsuario = Convert.ToInt32(r["id"]);
            us1.NombreUsuario = r["cuenta"].ToString().Trim();
            us1.PassUsuario = r["password"].ToString().Trim();
            us1.EmailUsuario = r["email"].ToString().Trim();
            us1.FechaRegUsuario = Convert.ToDateTime(r["fechareg"]);
            us1.CXBaseUsuario = Convert.ToInt32(r["coordenada_x"]);
            us1.CYBaseUsuario = Convert.ToInt32(r["coordenada_y"]);
            us1.CXCuadranteUsuario = Convert.ToInt32(r["cuadrante_x"]);
            us1.CYCuadranteUsuario = Convert.ToInt32(r["cuadrante_y"]);
            us1.NombrePlaneta = r["nomplaneta"].ToString().Trim();

            return us1;
        }

        /// <summary>
        /// Obtiene un usuario a partir del nombre de cuenta del mismo.
        /// </summary>
        /// <param name="nomus">Nombre de cuenta del usuario</param>
        /// <returns>Devuelve un objeto de tipo ENUsuario con los datos del usuario indicado. Null si no se ha encontrado</returns>
        public ENUsuario BuscarUsuarioPorCuenta(string nomus)
        {
            string selectUs = "cuenta = \'" + nomus.ToString() + "\'";
            ENUsuario us1 = new ENUsuario();

            DataTable tabla = new DataTable();
            DataRow r = null;

            tabla = vdb.Tables["Usuarios"];
            try
            {
                r = tabla.Select(selectUs)[0];
            }
            catch (Exception)
            {
                return null;
            }
            // Insertamos los datos en el nuevo usuario.
            us1.IDUsuario = Convert.ToInt32(r["id"]);
            us1.NombreUsuario = r["cuenta"].ToString().Trim();
            us1.PassUsuario = r["password"].ToString().Trim();
            us1.EmailUsuario = r["email"].ToString().Trim();
            us1.FechaRegUsuario = Convert.ToDateTime(r["fechareg"]);
            us1.CXBaseUsuario = Convert.ToInt32(r["coordenada_x"]);
            us1.CYBaseUsuario = Convert.ToInt32(r["coordenada_y"]);
            us1.CXCuadranteUsuario = Convert.ToInt32(r["cuadrante_x"]);
            us1.CYCuadranteUsuario = Convert.ToInt32(r["cuadrante_y"]);
            us1.NombrePlaneta = r["nomplaneta"].ToString().Trim();

            return us1;
        }

        /// <summary>
        /// Obtiene una lista con todos los usuarios de la tabla usuarios, cuyos
        /// campos coinciden con los parametros pasados.
        /// </summary>
        /// <returns> Lista de objetos ENUsuario que contienen los usuarios pedidos</returns>
        public ArrayList BuscarUsuariosPorCampos(string nomus, string email, string bx, string by, string cx, string cy, string fecha)
        {
            ArrayList lista = new ArrayList();
            DataTable tabla = new DataTable();
            DataRow[] filasEncontradas;

            tabla = vdb.Tables["Usuarios"];
            string miselect = "";
            int numcampos = 0;
            if (nomus != "")
            {
                miselect += @"cuenta LIKE '%" + nomus + "%'";
                numcampos++;
            }
            if (email != "")
            {
                if (numcampos > 0)
                {
                    miselect += " AND ";
                }
                miselect += @"email LIKE '%" + email + "%'";
                numcampos++;
            }
            if (fecha != "")
            {
                if (numcampos > 0)
                {
                    miselect += " AND ";
                }
                miselect += @"fechareg = '" + fecha + "'";
                numcampos++;
            }
            if (bx !="" && by != "")
            {//Caso en que quiero filtar por base también.
                if (numcampos > 0)
                {
                    miselect += " AND ";
                }
                miselect += "coordenada_x = \'" + bx + "\' AND coordenada_y = \'" + by + "\'";
                numcampos++;
            }
            if (cx !="" && cy != "")
            {//Caso en que quiero filtar por cuadrante también.
                if (numcampos > 0)
                {
                    miselect += " AND ";
                }
                miselect += "cuadrante_x = \'" + cx + "\' AND cuadrante_y = \'" + cy + "\'";
                numcampos++;
            }

            //Obtengo una matriz de filas, con las fila en las que el campo coincide
            filasEncontradas = tabla.Select(miselect);

            //Compruebo si ha encontrado alguna coincidencia sino devuelvo null
            if (filasEncontradas.Length <= 0)
            {
                return null;
            }
            //Recorro las filas encontradas y selecciono los usuarios.
            for (int i = 0; i < filasEncontradas.Length; i++)
            {
                ENUsuario us1=new ENUsuario();
                us1.IDUsuario = Convert.ToInt32(filasEncontradas[i][0]);
                us1.NombreUsuario = filasEncontradas[i][1].ToString().Trim();
                us1.PassUsuario = filasEncontradas[i][2].ToString().Trim();
                us1.EmailUsuario = filasEncontradas[i][3].ToString().Trim();
                us1.FechaRegUsuario = Convert.ToDateTime(filasEncontradas[i][4]);
                us1.CXBaseUsuario = Convert.ToInt32(filasEncontradas[i][5]);
                us1.CYBaseUsuario = Convert.ToInt32(filasEncontradas[i][6]);
                us1.CXCuadranteUsuario = Convert.ToInt32(filasEncontradas[i][7]);
                us1.CYCuadranteUsuario = Convert.ToInt32(filasEncontradas[i][8]);
                us1.NombrePlaneta = filasEncontradas[i][9].ToString().Trim();
                lista.Add(us1);
            }
            return lista;

 
        }








        /// <summary>
        /// Devuelve el nombre del último usuario registrado.
        /// </summary>
        /// <returns>Devuelve el nombre del administrador.</returns>
        public string getUltimo()
        {
            DataTable t = new DataTable();
            DataRow dr = null;

            t = vdb.Tables["Usuarios"];
            dr = t.Rows[0];
            return dr["cuenta"].ToString().Trim();
        }

        /// <summary>
        /// Obtiene el número de usuarios que hay en la BD
        /// </summary>
        /// <returns> Entero con el número de usuarios </returns>
        public int getNumUsuarios()
        {
            DataTable t = new DataTable();
            t = vdb.Tables["Usuarios"];
            return t.Rows.Count;
        }

        /// <summary>
        /// Permite insertar un Usuario en la tabla usuarios de la BD.
        /// </summary>
        /// <param name="us"> Objeto de tipo ENUsuario con los datos del usuario</param>
        /// <returns>True si se trata de una inserción. False si es una modificación</returns>
        public bool InsertarUsuario(ENUsuario us){
            DataTable tabla = new DataTable();
            tabla = vdb.Tables["Usuarios"];

            DataRow fila = null;
            bool hecho = false;

            string select = "id = "+ us.IDUsuario + " ";

            try
            {
                fila = tabla.Select(select)[0];


                fila["cuenta"] = us.NombreUsuario;
                fila["password"] = us.PassUsuario;
                fila["email"] = us.EmailUsuario;
                fila["coordenada_x"] = us.CXBaseUsuario;
                fila["coordenada_y"] = us.CYBaseUsuario;
                fila["cuadrante_x"] = us.CXCuadranteUsuario;
                fila["cuadrante_y"] = us.CYCuadranteUsuario;
                fila["nomplaneta"] = us.NombrePlaneta;

                SqlCommandBuilder comando = new SqlCommandBuilder(da);

                da.Update(vdb, "Usuarios");
            }
            catch (Exception)//Nuevo usuario
            {
                fila = tabla.NewRow();

                //fila["id"] = 
                fila["cuenta"] = us.NombreUsuario;
                fila["password"] = us.PassUsuario;
                fila["email"] = us.EmailUsuario;
                fila["fechareg"] = us.FechaRegUsuario;
                fila["coordenada_x"] = us.CXBaseUsuario;
                fila["coordenada_y"] = us.CYBaseUsuario;
                fila["cuadrante_x"] = us.CXCuadranteUsuario;
                fila["cuadrante_y"] = us.CYCuadranteUsuario;
                fila["nomplaneta"] = us.NombrePlaneta;

                tabla.Rows.Add(fila);

                SqlCommandBuilder command = new SqlCommandBuilder(da);

                da.Update(vdb, "Usuarios");

                vdb.Tables["Usuarios"].Clear();

                da.SelectCommand = new SqlCommand("select * from usuarios order by cuenta asc", c);

                da.Fill(vdb, "Usuarios");

                hecho = true;
            }
            return hecho;

        }

        /// <summary>
        /// Permite eleiminar un usuario de la tabla usuarios de la BD dado su ID
        /// </summary>
        /// <param name="iduser">Id del usuario</param>
        public void EliminarUsuario(int iduser)
        {
            string select = "id = \'" + iduser.ToString() + "\'";

            DataTable t = vdb.Tables["Usuarios"];

            try
            {
                DataRow r = t.Select(select)[0];
                r.Delete();

                //Ahora tengo que eliminar de las BD's UsuariosEdificio y UsuariosUnidades todos los
                //edificios del usuario.
                CADEdificioUsuario.Instancia.DarDeBajaTodosEdificiosUsuario(iduser);
                //Lo mismo para todas las unidades.
                CADUnidadesUsuario.Instancia.DarDeBajaTodasUnidadesUsuario(iduser);

                SqlCommandBuilder command = new SqlCommandBuilder(da);

                // Actualizamos los cambios en la BD real.
                da.Update(vdb, "Usuarios");

                //Indicar la actividad de que se ha eliminado un usuario.
            }
            catch
            {
                 //Caso en el que no se ha encontrado el usuario. No se hace nada.
            }
        }

        /// <summary>
        /// Compueba si dadas unas coordenadas de base y cuadrante, o las coordenadas y un id de usuario
        /// , ya estan ocupadas por una base.
        /// </summary>
        /// <param name="bx">Coordenada x de la base</param>
        /// <param name="by">Coordenada y de la base</param>
        /// <param name="cx">Coordenada x del cuadrante</param>
        /// <param name="cy">Coordenada y del cuadrante</param>
        /// <param name="IDusuarioMostrado"> Id del usuario, -1 si es una inserción</param>
        /// <returns>True si hay una base, False en caso contrario</returns>
        public bool EstaOcupada(string bx, string by, string cx, string cy, int IDusuarioMostrado)
        {
            ArrayList lista = new ArrayList();
            DataTable tabla = new DataTable();
            DataRow[] filasEncontradas;

            tabla = vdb.Tables["Usuarios"];
            string miselect = "";
            //Si estoy en edición tengo en cuenta que las coordenadas pueden ser las mismas.
            if (IDusuarioMostrado != -1)
            {
                miselect += "id <> \'" + IDusuarioMostrado.ToString() + "\' AND ";
            }
            miselect += "coordenada_x = \'" + bx + "\' AND coordenada_y = \'" + by + "\' AND cuadrante_x = \'" + cx + "\' AND cuadrante_y = \'" + cy + "\'";

            //Obtengo una matriz de filas, con las fila en las que el campo coincide
            filasEncontradas = tabla.Select(miselect);

            //Compruebo si ha encontrado alguna coincidencia
            if (filasEncontradas.Length <= 0)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        /// <summary>
        /// Comprueba si dado un nombre de usuario, o un nombre de usuario y un id de usuario
        /// ese nombre de cuenta ya existe en la BD, en la tabla Usuarios
        /// </summary>
        /// <param name="nombre">Cadena con el nombre del usurario</param>
        /// <param name="IDusuarioMostrado">Id del usuario si no es una inserción, -1 en otro caso</param>
        /// <returns>True si se encuentra tal usuario</returns>
        public bool ExisteElUsuario(string nombre, int IDusuarioMostrado)
        {
            ArrayList lista = new ArrayList();
            DataTable tabla = new DataTable();
            DataRow[] filasEncontradas;

            tabla = vdb.Tables["Usuarios"];
            string miselect = "";
            //Si estoy en edición tengo en cuenta que el nombre de usuario puede ser el mismo
            if (IDusuarioMostrado != -1)
            {
                miselect += "id <> \'" + IDusuarioMostrado.ToString() + "\' AND ";
            }
            miselect += "cuenta = \'" + nombre + "\'";

            //Obtengo una matriz de filas, con las fila en las que el campo coincide
            filasEncontradas = tabla.Select(miselect);

            //Compruebo si ha encontrado alguna coincidencia
            if (filasEncontradas.Length <= 0)
            {
                return false;
            }
            else
            {
                return true;
            }

        }


    }
}
